/* ----------------------------------------------------------------------
 *	Shadow Quest
 *	Copyright (C) 2009 Prageeth Silva <prageeth@thenewcoders.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *  ----------------------------------------------------------------------
 */
package sq;

import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.HashMap;

import map.Weather;

import org.newdawn.slick.Animation;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;

import sq.game.GameCursor.CursorState;

public class ImageLoader {

    private static final int SUBMENU_FRAMES = 5, SUBMENU_INTERVAL = 100;
    private static HashMap<String, Image> loadedImages;
    private static Image panelBgHP, panelBgXP;
    private static Image barHP, groundBones, flyingBones;
    private static Image sliderPointer, sliderPointerHover, sliderBG;
    private static Image wRain;
    private static Image wHours[], wLightning[];
    // TODO private static
    private static MouseAnimation gameCursors[];
    private static Animation menuCursor;
    private static Animation menuError, menuBusy;
    private static Animation subMenuOpen, subMenuClose;
    private static boolean gameLoaded, menuLoaded;
    private static Image epilogue[], prologue[];

    public static void initialise() {

        ImageLoader.loadedImages = new HashMap<String, Image>();
        ImageLoader.gameLoaded = false;
        ImageLoader.menuLoaded = false;

    }

    public static void loadGameImages()
            throws SlickException {

        if (!ImageLoader.isGameImagesLoaded()) {

            String dirPath = "assets/res/";
            ImageLoader.barHP = new Image(dirPath + "hp.png");

            dirPath = "assets/units/";
            ImageLoader.groundBones = new Image(dirPath + "bones.png");
            ImageLoader.flyingBones = new Image(dirPath + "flying_bones.png");

            dirPath = "assets/res/panel/";
            ImageLoader.panelBgHP = new Image(dirPath + "hp_bg.png");
            ImageLoader.panelBgXP = new Image(dirPath + "xp_bg.png");

            ImageLoader.loadGameCursors();
            ImageLoader.loadWeatherImages();

            ImageLoader.setGameImagesLoaded(true);

        }

    }

    private static void loadGameCursors()
            throws SlickException {

        String dirPath = "assets/res/cursors/";
        int len = CursorState.values().length;

        ImageLoader.gameCursors = new MouseAnimation[len];

        for (int i = 0; i < len; i++) {
            Image img = new Image(dirPath + String.valueOf(CursorState.values()[i]) + ".png");
            ImageLoader.gameCursors[i] = new MouseAnimation(img, 70, 70);
        }

    }

    private static void loadWeatherImages()
            throws SlickException {

        String path = "assets/weather/";
        String dirPath = path;
        String file = "-hours.png";
        ImageLoader.wRain = new Image(dirPath + "rain.png");

        int max = 24;
        ImageLoader.wHours = new Image[max];

        for (int i = 0; i < max; i++) {
            ImageLoader.wHours[i] = new Image(dirPath + i + file);
        }

        dirPath = path + "lightning/";
        file = "_lightning.png";
        max = Weather.LIGHTNING_MAX_IMAGES;
        ImageLoader.wLightning = new Image[max];

        for (int i = 0; i < max; i++) {
            ImageLoader.wLightning[i] = new Image(dirPath + i + file);
        }

    }

    public static void loadMenuImages()
            throws SlickException {
        if (!ImageLoader.isMenuImagesLoaded()) {

            String dirPath = "assets/menu/objects/";
            ImageLoader.sliderPointer = new Image(dirPath + "slider_pointer.png");
            ImageLoader.sliderPointerHover = new Image(dirPath + "hover_slider_pointer.png");
            ImageLoader.sliderBG = new Image(dirPath + "slider_bg.png");

            dirPath = "assets/res/cursors/";
            ImageLoader.menuCursor = new Animation(new SpriteSheet(dirPath + "MENU.png", 70, 70), 100);
            ImageLoader.menuCursor.setAutoUpdate(false);

            dirPath = "assets/res/";
            ImageLoader.menuError = new Animation(new SpriteSheet(dirPath + "error.png", 70, 70), 100);
            ImageLoader.menuBusy = new Animation(new SpriteSheet(dirPath + "busy.png", 70, 70), 100);

            dirPath = "assets/menu/submenu/";
            String file = "_submenu.png";
            Image subMenuO[] = new Image[SUBMENU_FRAMES];
            Image subMenuC[] = new Image[SUBMENU_FRAMES];
            int dur[] = new int[SUBMENU_FRAMES];
            for (int i = 0; i < SUBMENU_FRAMES; i++) {
                Image img = new Image(dirPath + i + file);
                img.setAlpha(0.95f);
                subMenuO[i] = img;
                subMenuC[SUBMENU_FRAMES - 1 - i] = img;
                dur[i] = SUBMENU_INTERVAL;
            }
            ImageLoader.subMenuOpen = new Animation(subMenuO, dur);
            ImageLoader.subMenuClose = new Animation(subMenuC, dur);
            ImageLoader.subMenuOpen.setLooping(false);
            ImageLoader.subMenuClose.setLooping(false);

            ImageLoader.setMenuImagesLoaded(true);

        }

    }

    public static Image getLoadedImage(String fileName)
            throws SlickException {
        Image i = ImageLoader.loadedImages.get(fileName);
        if (i == null) {
            i = new Image(fileName);
            ImageLoader.loadedImages.put(fileName, i);
        }
        return i;
    }

    private static void setGameImagesLoaded(boolean status) {
        ImageLoader.gameLoaded = status;
    }

    private static void setMenuImagesLoaded(boolean status) {
        ImageLoader.menuLoaded = status;
    }

    public static boolean isGameImagesLoaded() {
        return ImageLoader.gameLoaded;
    }

    public static boolean isMenuImagesLoaded() {
        return ImageLoader.menuLoaded;
    }

    /** Gets the HP Bar image used to render.
     * @return The image.
     */
    public static Image getBarHP() {
        return ImageLoader.barHP;
    }

    public static Image getGroundUnitBones() {
        return ImageLoader.groundBones;
    }

    public static Image getFlyingUnitBones() {
        return ImageLoader.flyingBones;
    }

    public static Image getSliderPointer() {
        return ImageLoader.sliderPointer;
    }

    public static Image getSliderPointerHover() {
        return ImageLoader.sliderPointerHover;
    }

    public static Image getSliderBG() {
        return ImageLoader.sliderBG;
    }

    public static Animation getMenuError() {
        return ImageLoader.menuError;
    }

    public static Animation getMenuCursor() {
        return ImageLoader.menuCursor;
    }

    public static Animation getBusyAnimation() {
        return ImageLoader.menuBusy;
    }

    public static Animation getSubMenuOpen() {
        return ImageLoader.subMenuOpen;
    }

    public static Animation getSubMenuClose() {
        return ImageLoader.subMenuClose;
    }

    public static MouseAnimation getGameCursor(CursorState state) {
        return ImageLoader.gameCursors[state.ordinal()];
    }

    public static Image getWeatherRain() {
        return ImageLoader.wRain;
    }

    public static Image[] getWeatherHours() {
        return ImageLoader.wHours;
    }

    public static Image getWeatherHour(int hour) {
        return ImageLoader.wHours[hour];
    }

    public static Image[] getWeatherLightnings() {
        return ImageLoader.wLightning;
    }

    public static Image getWeatherLightning(int index) {
        return ImageLoader.wLightning[index];
    }

    public static Image getPanelBgHP() {
        return ImageLoader.panelBgHP;
    }

    public static Image getPanelBgXP() {
        return ImageLoader.panelBgXP;
    }

    /** Loads the epilogue images.
     */
    public static boolean loadEpilogueImages(String path)
            throws SlickException {

        String dirPath = path + "epilogue/";
        File dir = new File(dirPath);

        FilenameFilter filter = new FilenameFilter()
        {
            public boolean accept(File dir, String name)
            {
                return name.endsWith(".jpg");
            }
        };

        String[] images = dir.list(filter);
        if (images == null)
        {
            return false;
        }
        else
        {
            epilogue = new Image[images.length];
            Arrays.sort(images);
            for (int i = 0; i < images.length; i++)
            {
                epilogue[i] = new Image(dirPath + images[i]);
            }
        }

        return true;

    }

    /** Loads the epilogue images.
     */
    public static boolean loadPrologueImages(String path)
            throws SlickException {

        String dirPath = path + "prologue/";
        File dir = new File(dirPath);

        FilenameFilter filter = new FilenameFilter()
        {
            public boolean accept(File dir, String name)
            {
                return name.endsWith(".jpg");
            }
        };

        String[] images = dir.list(filter);
        if (images == null)
        {
            return false;
        }
        else
        {
            prologue = new Image[images.length];
            Arrays.sort(images);
            for (int i = 0; i < images.length; i++)
            {
                prologue[i] = new Image(dirPath + images[i]);
            }
        }

        return true;

    }

    public static Image[] getEpilogueFrames() {
        return epilogue;
    }

    public static Image[] getPrologueFrames() {
        return prologue;
    }
}
